package com.symone.webcms.controller.web;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.symone.webcms.common.Constants;
import com.symone.webcms.controller.base.BaseController;
import com.symone.webcms.model.*;
import com.symone.webcms.model.vo.PermissionVO;
import com.symone.webcms.service.*;
import com.symone.webcms.util.CommonUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;
import java.util.*;

@Controller
@RequestMapping("/cms/sys")
public class SysController extends BaseController {

    @Autowired
    public LanguageService languageService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private MenuActionService actionService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private ScheduleTaskService taskService;

    @RequiresPermissions("sys:lang:index")
    @RequestMapping(value = "/language/index", method = RequestMethod.GET)
    public ModelAndView languageList() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/language/index");
        return mv;
    }

    @RequiresPermissions("sys:lang:add")
    @RequestMapping(value = "/language/add", method = RequestMethod.GET)
    public ModelAndView languageForm() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/language/form");
        mv.addObject("lang", new Language());
        return mv;
    }

    @RequiresPermissions("sys:lang:edit")
    @RequestMapping(value = "/language/edit", method = RequestMethod.GET)
    public ModelAndView languageForm(Long id) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/language/form");
        mv.addObject("lang", languageService.selectById(id));
        return mv;
    }

    @RequiresPermissions("sys:role:index")
    @RequestMapping(value = "/role/index", method = RequestMethod.GET)
    public ModelAndView roleList() {
        List<Role> roles = roleService.selectList(new EntityWrapper<Role>().eq("deleted",0));

        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/role/index");
        mv.addObject("roles",roles);
        return mv;
    }

    @RequiresPermissions("sys:role:add")
    @RequestMapping(value = "/role/add", method = RequestMethod.GET)
    public ModelAndView roleAdd() {
        List<Menu> menutree = getMenuActions();
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/role/form");
        mv.addObject("role", new Role());
        mv.addObject("menus", menutree);
        return mv;
    }

    @RequiresPermissions("sys:role:edit")
    @RequestMapping(value = "/role/edit", method = RequestMethod.GET)
    public ModelAndView roleEdit(Long id) {
        Role role = roleService.selectById(id);
        Set<PermissionVO> permissions = roleService.fetchPermissionsById(id);
        Set<String> codes = new HashSet<>();
        for(PermissionVO pm : permissions){
            if(pm != null) codes.add(pm.getCode());
        }
        List<Menu> menutree = getMenuActions();
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/role/form");
        mv.addObject("role", role);
        mv.addObject("menus", menutree);
        mv.addObject("codes", codes);
        return mv;
    }

    @RequiresPermissions("sys:user:index")
    @RequestMapping(value = "/user/index", method = RequestMethod.GET)
    public ModelAndView userList() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/user/index");
        mv.addObject("roles",roleService.selectList(new EntityWrapper<Role>().where("deleted=0")));
        return mv;
    }

    @RequiresPermissions("sys:user:add")
    @RequestMapping(value = "/user/add", method = RequestMethod.GET)
    public ModelAndView userAdd() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/user/form");
        mv.addObject("user",new User());
        mv.addObject("roles",roleService.selectList(new EntityWrapper<Role>().where("deleted=0")));
        return mv;
    }

    @RequiresPermissions("sys:user:edit")
    @RequestMapping(value = "/user/edit", method = RequestMethod.GET)
    public ModelAndView userEdit(Long id) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/user/form");
        User user = userService.selectById(id);
        mv.addObject("user",user);
        mv.addObject("roles",roleService.selectList(new EntityWrapper<Role>().where("deleted=0").orderBy("create_time",false)));
        return mv;
    }

    @RequestMapping(value = "/setting", method = RequestMethod.GET)
    public ModelAndView setting() {
        List<Config> configs = configList("sys");
        Map<String,String> configMap = new HashMap<String,String>();
        for (Config config : configs){
            configMap.put(config.getCode(),config.getValue());
        }
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/setting");
        mv.addObject("config", configMap);
        return mv;
    }

    @RequiresPermissions("sys:task:index")
    @RequestMapping(value = "/task/index", method = RequestMethod.GET)
    public ModelAndView taskList() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/task/index");
        return mv;
    }

    @RequiresPermissions("sys:task:add")
    @RequestMapping(value = "/task/add", method = RequestMethod.GET)
    public ModelAndView taskAdd() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/task/form");
        mv.addObject("task",new ScheduleTask());
        return mv;
    }

    @RequiresPermissions("sys:task:edit")
    @RequestMapping(value = "/task/edit", method = RequestMethod.GET)
    public ModelAndView taskEdit(Long id) {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/sys/task/form");
        ScheduleTask task = taskService.selectById(id);
        mv.addObject("task",task);
        return mv;
    }

    private List<Menu> getMenuActions(){
        List<Menu> menus = menuService.selectList(new EntityWrapper<Menu>().eq("deleted",0).orderBy("sorting",true));
        List<Menu> menuList = new ArrayList<>();
        for(Menu menu : menus){
            if(menu.getPid() > 0){
                List<MenuAction> actions = actionService.selectList(new EntityWrapper<MenuAction>().eq("deleted", 0).and().eq("mcode", menu.getCode()));
                menu.setActions(actions);
            }
            menuList.add(menu);
        }
        return CommonUtil.list2Tree(menuList);
    }

    private List<Config> configList(String groupName){
        return configService.selectList(new EntityWrapper<Config>().where("deleted = 0 and code like CONCAT('"+groupName+"','%' ) "));
    }

}
